package com.csun.dsms.service.impl;

import com.csun.dsms.comment.base.enums.ErrorCodeEnum;
import com.csun.dsms.comment.base.exception.BusinessException;
import com.csun.dsms.comment.core.support.BaseService;
import com.csun.dsms.comment.core.support.CsunMessageSource;
import com.csun.dsms.mapper.DsmsUserMapper;
import com.csun.dsms.model.domain.DsmsRoleUser;
import com.csun.dsms.model.domain.DsmsUnitUser;
import com.csun.dsms.model.domain.DsmsUser;
import com.csun.dsms.model.dto.user.ResetPwdDto;
import com.csun.dsms.model.dto.user.UserDto;
import com.csun.dsms.model.dto.user.UserModifyPwdDto;
import com.csun.dsms.model.dto.user.UserQueryDto;
import com.csun.dsms.model.enums.UserSourceEnum;
import com.csun.dsms.model.enums.UserTypeEnum;
import com.csun.dsms.model.vo.staff.StaffVo;
import com.csun.dsms.model.vo.user.UserVo;
import com.csun.dsms.service.*;
import com.csun.dsms.utils.MD5;
import com.csun.dsms.utils.PublicUtil;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Preconditions;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author chisj chisj@foxmail.com
 * @version 1.0.0
 * @date 2021-08-31 15:25
 * @description: TODO
 */
@Service
@Transactional
public class DsmsUserServiceImpl extends BaseService<DsmsUser> implements DsmsUserService {

    @Resource
    private DsmsUserMapper dsmsUserMapper;
    @Resource
    private CsunMessageSource csunMessageSource;
    @Resource
    private TokenManager tokenManager;
    @Resource
    private DsmsRoleUserService dsmsRoleUserService;
    @Resource
    private DsmsUnitUserService dsmsUnitUserService;
    @Resource
    private DsmsStaffService dsmsStaffService;

    @Override
    public DsmsUser selectUserById(Long id) {

        return dsmsUserMapper.selectUserById(id);
    }

    /**
     * 用户登录
     *
     * @param username  the username
     * @param password  the password
     *
     * @return  the dsms user.
     */
    @Override
    public DsmsUser login(String username, String password) {

        // 校验账号不能为空
        Preconditions.checkArgument(PublicUtil.isNotEmpty(username));

        // 校验密码不能为空
        Preconditions.checkArgument(PublicUtil.isNotEmpty(password));

        DsmsUser dsmsUser = dsmsUserMapper.selectByLoginName(username);

        if (PublicUtil.isEmpty(dsmsUser)) {
            throw new BusinessException(ErrorCodeEnum.GB10011041);
        }

        if (dsmsUser.getStatus().equals("DISABLE")) {
            throw new BusinessException(ErrorCodeEnum.GB10011052);
        }

        StaffVo staffVo = dsmsStaffService.selectByUserId(dsmsUser.getId());
        if (PublicUtil.isNotEmpty(staffVo) && !staffVo.getApply().equals(1)) {
            throw new BusinessException(ErrorCodeEnum.GB10011052);
        }

        password = MD5.getMd5().getMD5ofStr(password);
        if (!password.equals(dsmsUser.getLoginPwd())) {
            throw new BusinessException(ErrorCodeEnum.GB10011042);
        }

        return dsmsUser;
    }

    /**
     * 查询用户列表.
     *
     * @param userQueryDto  the iser query dto
     *
     * @return  the user vo list.
     */
    @Override
    public List<UserVo> queryListWithPage(UserQueryDto userQueryDto) {

        PageHelper.startPage(userQueryDto.getPageNum(), userQueryDto.getPageSize());

        return dsmsUserMapper.queryListWithPage(userQueryDto);
    }

    /**
     * 保存用户信息
     *
     * @param userDto   the user dto
     * @param login     the login user
     *
     * @return  the int.
     */
    @Override
    public Integer save(UserDto userDto, DsmsUser login) {

        DsmsUser dsmsUser = new DsmsUser();
        BeanUtils.copyProperties(userDto, dsmsUser);
        dsmsUser.setUpdateInfo(login);

        DsmsUser userQuery =new DsmsUser();
        userQuery.setLoginName(dsmsUser.getLoginName());
        int count = dsmsUserMapper.selectCount(userQuery);
        if (count > 0) {
            throw new BusinessException(ErrorCodeEnum.GB10011032);
        }

        if (!checkMobileNo(null, dsmsUser.getMobileNo())) {
            // 存在重复的手机号
            throw new BusinessException(ErrorCodeEnum.GB10011031);
        }

        dsmsUser.setType(UserTypeEnum.OPERATE.getKey());
        dsmsUser.setUserSource(UserSourceEnum.INSERT.getKey());
        dsmsUser.setLoginPwd(MD5.getMd5().getMD5ofStr(dsmsUser.getLoginPwd()));

        Integer result = dsmsUserMapper.insertSelective(dsmsUser);
        if (result > 0) {
            DsmsRoleUser dsmsRoleUser = new DsmsRoleUser();
            dsmsRoleUser.setUserId(dsmsUser.getId());
            dsmsRoleUser.setRoleId(userDto.getRoleId());
            dsmsRoleUserService.save(dsmsRoleUser);

            DsmsUnitUser dsmsUnitUser = new DsmsUnitUser();
            dsmsUnitUser.setUserId(dsmsUser.getId());
            dsmsUnitUser.setUnitId(userDto.getUnitId());
            dsmsUnitUserService.save(dsmsUnitUser);
        }

        return result;
    }

    /**
     * 修改用户信息
     *
     * @param userDto   the user dto
     * @param login     the login user
     *
     * @return  the int.
     */
    @Override
    public Integer edit(UserDto userDto, DsmsUser login) {

        DsmsUser dsmsUser = new DsmsUser();
        BeanUtils.copyProperties(userDto, dsmsUser);
        dsmsUser.setUpdateInfo(login);
        dsmsUser.setLoginPwd(null);

        DsmsUser dsmsUserQuery = dsmsUserMapper.selectByPrimaryKey(userDto.getId());
        if (PublicUtil.isEmpty(dsmsUserQuery)) {
            throw new BusinessException(ErrorCodeEnum.GB10011036);
        }

        if (PublicUtil.isNotEmpty(dsmsUser.getLoginName())) {
            if (!checkLoginName(userDto.getId(), dsmsUser.getLoginName())) {
                throw new BusinessException(ErrorCodeEnum.GB10011032);
            }
        }

        if (PublicUtil.isNotEmpty(dsmsUser.getMobileNo())) {
            if (!checkMobileNo(userDto.getId(), dsmsUser.getMobileNo())) {
                // 存在重复的手机号
                throw new BusinessException(ErrorCodeEnum.GB10011031);
            }
        }

        if (PublicUtil.isNotEmpty(userDto.getRoleId())) {

            DsmsRoleUser dsmsRoleUser = new DsmsRoleUser();
            dsmsRoleUser.setUserId(dsmsUser.getId());
            dsmsRoleUserService.delete(dsmsRoleUser);

            dsmsRoleUser.setRoleId(userDto.getRoleId());
            dsmsRoleUserService.save(dsmsRoleUser);
        }

        if (PublicUtil.isNotEmpty(userDto.getUnitId())) {

            DsmsUnitUser dsmsUnitUser = new DsmsUnitUser();
            dsmsUnitUser.setUserId(dsmsUser.getId());
            dsmsUnitUserService.delete(dsmsUnitUser);

            dsmsUnitUser.setUnitId(userDto.getUnitId());
            dsmsUnitUserService.save(dsmsUnitUser);
        }

        return dsmsUserMapper.updateByPrimaryKeySelective(dsmsUser);
    }

    /**
     * 根据Id修改用户状态
     *
     * @param dsmsUser  the dsms user
     * @param login     the login user
     *
     * @return  the int.
     */
    @Override
    public Integer modifyUserStatusById(DsmsUser dsmsUser, DsmsUser login) {

        DsmsUser dsmsUserQuery = dsmsUserMapper.selectByPrimaryKey(dsmsUser.getId());
        if (PublicUtil.isEmpty(dsmsUserQuery)) {
            throw new BusinessException(ErrorCodeEnum.GB10011036);
        }

        return dsmsUserMapper.updateByPrimaryKeySelective(dsmsUser);
    }

    /**
     * 通过Id删除用户
     *
     * @param userId    the user id
     *
     * @return  the int.
     */
    @Override
    public Integer deleteUserById(Long userId) {

        // 删除用户角色
        DsmsRoleUser dsmsRoleUser = new DsmsRoleUser();
        dsmsRoleUser.setUserId(userId);
        dsmsRoleUserService.delete(dsmsRoleUser);

        // 删除用户单位
        DsmsUnitUser dsmsUnitUser = new DsmsUnitUser();
        dsmsUnitUser.setUserId(userId);
        dsmsUnitUserService.delete(dsmsUnitUser);

        return dsmsUserMapper.deleteByPrimaryKey(userId);
    }

    /**
     * 用户修改密码
     *
     * @param userModifyPwdDto  the user modify password dto
     * @param login the login user
     *
     * @return  the int.
     */
    @Override
    public Integer userModifyPwd(UserModifyPwdDto userModifyPwdDto, DsmsUser login) {

        // 判断密码是否一致
        Preconditions.checkArgument(userModifyPwdDto.getNewPassword().equals(userModifyPwdDto.getConfirmPwd()),
                csunMessageSource.getMessage("password.not.equal", null));

        DsmsUser user = dsmsUserMapper.findByLoginName(userModifyPwdDto.getLoginName());
        if (PublicUtil.isEmpty(user)) {
            throw new BusinessException(ErrorCodeEnum.GB10011036);
        }

        String oldPwd = user.getLoginPwd();

        if (!MD5.getMd5().getMD5ofStr(userModifyPwdDto.getOldPassword()).equals(oldPwd)) {
            throw new BusinessException(ErrorCodeEnum.GB10011034);
        }

        if (MD5.getMd5().getMD5ofStr(userModifyPwdDto.getNewPassword()).equals(oldPwd)) {
            throw new BusinessException(ErrorCodeEnum.GB10011035);
        }

        DsmsUser dsmsUserUpt = new DsmsUser();
        dsmsUserUpt.setId(user.getId());
        dsmsUserUpt.setLoginPwd(MD5.getMd5().getMD5ofStr(userModifyPwdDto.getNewPassword()));
        dsmsUserUpt.setIsChangedPwd(Short.valueOf("1"));
        dsmsUserUpt.setUpdateInfo(login);

        Integer result = dsmsUserMapper.updateByPrimaryKeySelective(dsmsUserUpt);
        if (result > 0) {
            // 刷新token
            tokenManager.deleteToken(user.getId());
        }

        return result;
    }

    /**
     * 重置用户密码
     *
     * @param resetPwdDto   the reset password dto
     * @param login         the login user
     *
     * @return
     */
    @Override
    public Integer resetPwd(ResetPwdDto resetPwdDto, DsmsUser login) {

        // 判断密码是否一致
        Preconditions.checkArgument(resetPwdDto.getPassword().equals(resetPwdDto.getConfirmPwd()),
                csunMessageSource.getMessage("password.not.equal", null));

        DsmsUser dsmsUserQuery = dsmsUserMapper.selectByPrimaryKey(resetPwdDto.getUserId());
        if (PublicUtil.isEmpty(dsmsUserQuery)) {
            throw new BusinessException(ErrorCodeEnum.GB10011036);
        }

        // 校验密码是否一致
        if (MD5.getMd5().getMD5ofStr(resetPwdDto.getPassword()).equals(dsmsUserQuery.getLoginPwd())) {
            throw new BusinessException(ErrorCodeEnum.GB10011035);
        }

        // 更新密码
        DsmsUser uacUserUpt = new DsmsUser();
        uacUserUpt.setId(resetPwdDto.getUserId());
        uacUserUpt.setLoginPwd(MD5.getMd5().getMD5ofStr(resetPwdDto.getPassword()));
        uacUserUpt.setUpdateInfo(login);
        Integer result = dsmsUserMapper.updateByPrimaryKeySelective(uacUserUpt);

        // 刷新token
        tokenManager.deleteToken(resetPwdDto.getUserId());

        return result;
    }

    @Override
    public boolean checkLoginName(Long userId, String loginName) {

        Preconditions.checkArgument(PublicUtil.isNotEmpty(loginName),
                csunMessageSource.getMessage("login.name.null", null));

        Example example = new Example(DsmsUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("loginName", loginName);
        if (userId != null) {
            criteria.andNotEqualTo("id", userId);
        }

        int result = selectCountByExample(example);

        return result < 1;
    }

    @Override
    public boolean checkIdCard(Long userId, String idCard) {

        Preconditions.checkArgument(PublicUtil.isNotEmpty(idCard),
                csunMessageSource.getMessage("id.card.null", null));

        Example example = new Example(DsmsUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("idCard", idCard);
        if (userId != null) {
            criteria.andNotEqualTo("id", userId);
        }

        int result = selectCountByExample(example);
        return result < 1;
    }

    @Override
    public boolean checkMobileNo(Long userId, String mobileNo) {

        Preconditions.checkArgument(PublicUtil.isNotEmpty(mobileNo),
                csunMessageSource.getMessage("mobile.no.null", null));

        Example example = new Example(DsmsUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("mobileNo", mobileNo);
        if (userId != null) {
            criteria.andNotEqualTo("id", userId);
        }

        int result = selectCountByExample(example);

        return result < 1;
    }
}
